package com.googlecode.groovy_toy_orm

import com.googlecode.groovy_toy_orm.internal.Util
import groovy.sql.Sql

/**
 * @author: DavydovMD
 * Date: 11.04.13
 * Time: 14:24
 */
class MultiTableMapper<T> extends MultiMapper implements DbSourced<T> {
    Class<T> beanClass

    protected Map<SingleDbTableMapper, MapperBinding> mapperBindings = [:]
    protected Map<String, Closure<Sql>> databases = [:] //url -> database
    protected Map<String, Set<SingleDbTableMapper>> mappersPerUrl = [:] //url -> mappers
    protected List<MapperBinding> mapperBindingsParameter = []

    @Delegate
    final DbSourced<T> unmarshaller




    public boolean isMultiDb() {
        if (mappersPerUrl.size() <= 1) {
            return false
        }
        return true
    }

    @Override
    public List<SingleDbTableMapper> getMappers() {
        super.mappers as List<SingleDbTableMapper>
    }

    MultiTableMapper(List<SingleDbTableMapper> mappers, Class beanClass, List<MapperBinding> bindings = []) {
        super(mappers as List<Mapper>)
        this.beanClass = beanClass
        this.mapperBindingsParameter = bindings

        bindings.each {
            mapperBindings.put it.mapper as SingleDbTableMapper, it
        }

        mappers.each { SingleDbTableMapper mapper ->
            if (bindings.grep { MapperBinding binding ->
                binding.mapper == mapper }.isEmpty()) {
                mapperBindings.put mapper, new MapperBinding(mapper)
            }


            String url = mapper.getDbUrl()
            if (!mappersPerUrl.containsKey(url)) {
                mappersPerUrl.put(url, new HashSet([mapper]))
                databases.put(url, mapper.dbGetter)
            } else {
                mappersPerUrl.get(url).add(mapper)
            }
        }

        unmarshaller = new Unmarshaller(this)
    }


    public Map<String, Set<SingleDbTableMapper>> getDbMappers() {
        return mappersPerUrl
    }

    @Override
    public SingleDbTableMapper findMapper(String field) {
        super.findMapper(field) as SingleDbTableMapper
    }

    MapperBinding getBinding(SingleDbTableMapper mapper) {
        mapperBindings.get(mapper)
    }

    //TODO: debug, add support for multiple databases

    QueryBuilder complexQuery(List<Class> classes, List<MapperBinding> bindings) {

        List<MultiTableMapper> mapperz = [this]

        classes.each {
            mapperz << it.invokeMethod("getMapper", null) as MultiTableMapper
        }

        QueryBuildingMapper qbMapper = new QueryBuildingMapper(mapperz, bindings)

        new SingleDbQueryBuilder(qbMapper)
    }
}
